package com.ruoyi.activity.service.impl;

import java.nio.BufferOverflowException;
import java.util.List;
import java.util.Objects;

import com.ruoyi.activity.mapper.UserMapper;
import com.ruoyi.activity.model.domain.User;
import com.ruoyi.client.model.dto.ApiUserUpdateRequest;
import com.ruoyi.client.vo.ApiLoginUserVO;
import com.ruoyi.activity.service.IUserService;
import com.ruoyi.activity.model.dto.ImportUserTemplateRequest;
import com.ruoyi.client.vo.UserLoginVO;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.exception.user.UserNotExistsException;
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.bean.BeanValidators;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.web.service.TokenService;
import org.apache.commons.collections4.CollectionUtils;
import org.mybatis.logging.Logger;
import org.mybatis.logging.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Validator;

import static com.ruoyi.client.model.constant.UserConstant.USER_LOGIN_STATE;

/**
 * 用户信息管理，存储用户及相关详情Service业务层处理
 *
 * @author ruoyi
 * @date 2024-06-27
 */
@Service
public class UserServiceImpl implements IUserService {

    @Resource
    private UserMapper userMapper;

    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    protected Validator validator;

    @Resource
    private AuthenticationManager authenticationManager;

    @Autowired
    private TokenService tokenService;

    /**
     * 查询用户信息管理，存储用户及相关详情
     *
     * @param id 用户信息管理，存储用户及相关详情主键
     * @return 用户信息管理，存储用户及相关详情
     */
    @Override
    public User selectUserById(Long id) {
        return userMapper.selectUserById(id);
    }

    /**
     * 用户注销
     *
     * @param request
     */
    @Override
    public boolean userLogout(HttpServletRequest request) {
        UserLoginVO loginUser = (UserLoginVO) request.getSession().getAttribute(USER_LOGIN_STATE);
        if (loginUser == null) {
            return false;
        }
        // 移除登录态
        request.getSession().removeAttribute(USER_LOGIN_STATE);
        return true;
    }


    /**
     * 查询用户信息管理，存储用户及相关详情列表
     *
     * @param user 用户信息管理，存储用户及相关详情
     * @return 用户信息管理，存储用户及相关详情
     */
    @Override
    public List<User> selectUserList(User user) {
        return userMapper.selectUserList(user);
    }

    /**
     * 新增用户信息管理，存储用户及相关详情
     *
     * @param user 用户信息管理，存储用户及相关详情
     * @return 结果
     */
    @Override
    public int insertUser(User user) {
        return userMapper.insertUser(user);
    }

    /**
     * 修改用户信息管理，存储用户及相关详情
     *
     * @param user 用户信息管理，存储用户及相关详情
     * @return 结果
     */
    @Override
    public int updateUser(User user) {
        return userMapper.updateUser(user);
    }

    /**
     * 批量删除用户信息管理，存储用户及相关详情
     *
     * @param ids 需要删除的用户信息管理，存储用户及相关详情主键
     * @return 结果
     */
    @Override
    public int deleteUserByIds(Long[] ids) {
        return userMapper.deleteUserByIds(ids);
    }

    /**
     * 删除用户信息管理，存储用户及相关详情信息
     *
     * @param id 用户信息管理，存储用户及相关详情主键
     * @return 结果
     */
    @Override
    public int deleteUserById(Long id) {
        return userMapper.deleteUserById(id);
    }


    /**
     * 导入账号
     */
    @Override
    public String importUser(List<ImportUserTemplateRequest> importUserTemplateRequestList, Boolean isUpdateSupport, String operName) {
        if (CollectionUtils.isEmpty(importUserTemplateRequestList)) {
            throw new ServiceException("导入项目账号数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        for (ImportUserTemplateRequest userTemplateDto : importUserTemplateRequestList) {
            try {
                // 验证是否存在这个项账号
                User existingUser = userMapper.selectUserByAccount(userTemplateDto.getAccount());
                if (Objects.isNull(existingUser)) {
                    BeanValidators.validateWithException(validator, userTemplateDto);
                    userTemplateDto.setCreateBy(operName);
                    User user = new User();
                    BeanUtils.copyProperties(userTemplateDto, user);
                    user.setUserPassword("12345678");
                    this.insertUser(user);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、账号 " + user.getAccount() + " 导入成功");
                } else if (isUpdateSupport) {
                    BeanValidators.validateWithException(validator, userTemplateDto);
                    userTemplateDto.setUpdateBy(operName);
                    User user = new User();
                    BeanUtils.copyProperties(userTemplateDto, user);
                    this.updateUser(user);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、账号 " + userTemplateDto.getAccount() + " 更新成功");
                } else {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、账号 " + userTemplateDto.getAccount() + " 已存在");
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、账号 " + userTemplateDto.getAccount() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(() -> msg, e);

            }
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，共有这些账号导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        StringBuilder allMsg = new StringBuilder();
        allMsg.append(successMsg);
        allMsg.append(failureMsg);
        return allMsg.toString();
    }

    /**
     * 用户登录
     *
     * @param account
     * @param userPassword
     * @param request
     * @return
     */
    @Override
    public UserLoginVO userLogin(String account, String userPassword, HttpServletRequest request) {
        User user = userMapper.selectUserByAccount(account);
        if (user == null) {
            throw new BaseException("账号不存在");
        }
        String password = user.getUserPassword();
        if (password != null && !password.equals(userPassword)) {
            throw new BaseException("用户账号或者密码错误");
        }
        // 3. 记录用户的登录态
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            System.out.print(cookie.getName());
            System.out.print(":");
            System.out.println(cookie.getValue());
        }
        UserLoginVO userLoginVO = new UserLoginVO();
        BeanUtils.copyProperties(user, userLoginVO);
        request.getSession().setAttribute(USER_LOGIN_STATE, userLoginVO);
        System.out.println((UserLoginVO) request.getSession().getAttribute(USER_LOGIN_STATE));
        return userLoginVO;
    }

    @Override
    public ApiLoginUserVO getLoginUserVO(User user) {
        if (user == null) {
            return null;
        }
        ApiLoginUserVO loginUserVO = new ApiLoginUserVO();
        org.springframework.beans.BeanUtils.copyProperties(user, loginUserVO);
        return loginUserVO;
    }

    @Override
    public UserLoginVO getUserLoginVO(HttpServletRequest request) {
        return (UserLoginVO) request.getSession().getAttribute(USER_LOGIN_STATE);
    }

    @Override
    public boolean updateById(ApiUserUpdateRequest userUpdateRequest, UserLoginVO loginUserVO) {
        Long userId = loginUserVO.getId();
        String newPassword = userUpdateRequest.getNewPassword();
        String newPasswordSecond = userUpdateRequest.getNewPasswordSecond();
        if (!newPassword.equals(newPasswordSecond)) {
            throw new BaseException("两次密码不同");
        }
        User oldUser = userMapper.selectUserById(userId);
        if (oldUser == null) {
            throw new BaseException("该用户不存在");
        }
        String userPassword = oldUser.getUserPassword();
        String oldPassword = userUpdateRequest.getOldUserPassword();
        if (!userPassword.equals(oldPassword)) {
            throw new BaseException("旧密码错误");
        }
        oldUser.setUserPassword(newPassword);
        int updateResult = userMapper.updateUser(oldUser);
        if (updateResult == 0) {
            throw new BaseException("更新失败");
        }
        return true;
    }

    @Override
    public User getLoginUser(HttpServletRequest request) {
        // 先判断是否已登录
        Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE);
        User currentUser = (User) userObj;
        if (currentUser == null || currentUser.getId() == null) {
            return null;
        }
        // 从数据库查询（追求性能的话可以注释，直接走缓存）
        long userId = currentUser.getId();
        currentUser = userMapper.selectUserById(userId);
        if (currentUser == null) {
            return null;
        }
        return currentUser;

    }

    @Override
    public User selectUserByAccount(String userAccount) {
        return userMapper.selectUserByAccount(userAccount);
    }

    /**
     * 登录前置校验
     *
     * @param username 用户名
     * @param password 用户密码
     */
    public void loginPreCheck(String username, String password) {
        // 用户名或密码为空 错误
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
            throw new UserNotExistsException();
        }
        // 密码如果不在指定范围内 错误
        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
            throw new UserPasswordNotMatchException();
        }
        // 用户名不在指定范围内 错误
        if (username.length() < UserConstants.USERNAME_MIN_LENGTH
                || username.length() > UserConstants.USERNAME_MAX_LENGTH) {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
            throw new UserPasswordNotMatchException();
        }
    }

    /**
     * 记录登录信息
     *
     * @param userId 用户ID
     */
    public void recordLoginInfo(Long userId) {
        User user = new User();
        user.setId(userId);
//        sysUser.setLoginIp(IpUtils.getIpAddr());
//        sysUser.setLoginDate(DateUtils.getNowDate());
//        userService.updateInformationDisclosureDocument(sysUser);
    }

}
